package com.msb.strategy.filter.impl;

import com.msb.common.constart.CacheConstant;
import com.msb.common.constart.RabbitMQConstants;
import com.msb.common.constart.SmsConstant;
import com.msb.common.enums.ExceptionEnums;
import com.msb.common.exception.GraceException;
import com.msb.common.model.StandardSubmit;
import com.msb.strategy.feign.BeaconCacheClient;
import com.msb.strategy.filter.StrategyFilter;
import com.msb.strategy.util.ChannelTransferUtil;
import com.msb.strategy.util.ErrorSendMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 路由策略，选择合适的运营商通道
 *
 * @Author: lmf
 * @Create: 2025/3/11 22:40
 * @module 1、选择通道，先根据客户绑定的通道信息，拿到全部通道
 * 2、根据权重信息，选择权重高的，并且确认绑定关系么得问题。
 * 3、直接获取到具体的通道，并且再次判断通道是否可用，以及运营商是否匹配
 * 4、预留了一个通道转换的口子（暂时里面什么都没做）
 * 5、封装好submit
 * 6、声明好队列，并且发送消息，等待短信网关模块处理
 */
@Slf4j
@Service(value = "route")
public class RouteStrategyFilter implements StrategyFilter {

    @Autowired
    private BeaconCacheClient beaconCacheClient;

    @Resource
    private ErrorSendMessage errorSendMessage;

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private AmqpAdmin amqpAdmin;


    @Override
    public void strategy(StandardSubmit submit) {
        log.info("路由策略");
        Long clientId = submit.getClientId();

        Set<Map> clientChannelMap = beaconCacheClient.sMembersToMap(CacheConstant.CLIENT_CHANNEL + clientId);

        // 根据权重进行排序
        Set<Map> clientTeeMap = new TreeSet<>(new Comparator<Map>() {

            @Override
            public int compare(Map o1, Map o2) {
                int o1Weight = Integer.parseInt(o1.get("clientChannelWeight").toString());
                int o2Weight = Integer.parseInt(o2.get("clientChannelWeight").toString());
                return o2Weight - o1Weight;
            }
        });
        // 添加到集合中 (默认按照权重排序)
        clientTeeMap.addAll(clientChannelMap);

        Map<String, Object> channel = null;
        Map<String, Object> clientChannel = null;
        boolean ok = false;


        //4、基于排好序的通道选择，权重更高的
        for (Map clientWeightChannel : clientTeeMap) {
            // 确定当前客户绑定通道是否可用
            if ((int) clientWeightChannel.get("isAvailable") != 0) {
                continue;
            }

            // 如果通道信息查询后，判断通道睡否可用，其次运营商可以匹配。
            channel = beaconCacheClient.hGetAll(CacheConstant.CHANNEL + clientWeightChannel.get("channelId"));

            // 当前通道是否可用
            if (channel == null || (int) channel.get("isAvailable") != 0) {
                continue;
            }

            // 获取通道的通讯方式
            int channelType = (int) channel.get("channelType");
            if (channelType != 0 && submit.getOperatorId() != channelType) {
                // 通道不是全网通，并且和当前手机号运营商不匹配
                continue;
            }

            // ===========找打了对应通道==============
            // 通道转换
            channel = ChannelTransferUtil.transfer(submit, channel);
            // 获取客户绑定的通道信息
            clientChannel = clientWeightChannel;
            ok = true;
            break;

        }

        if (!ok) {
            submit.setErrorMessage(ExceptionEnums.CHANNEL_ERROR.getMsg());
            errorSendMessage.sendErrorMessage(submit, ExceptionEnums.CHANNEL_ERROR);
        }

        //基于选择的通道封装submit的信息
        submit.setChannelId(Long.parseLong(channel.get("id") + ""));
        submit.setSrcNumber("" + channel.get("channelNumber") + clientChannel.get("clientChannelNumber"));

        // 声明好队列名称，并构建队列
        try {
            String queueName = RabbitMQConstants.SMS_GATEWAY + submit.getClientId();
            amqpAdmin.declareQueue(QueueBuilder.durable(queueName).build());
            rabbitTemplate.convertAndSend(queueName, submit);
        } catch (AmqpException e) {
            submit.setErrorMessage(e.getMessage());
            errorSendMessage.sendErrorMessage(submit);
            GraceException.display(e.getMessage(), ExceptionEnums.UNKNOWN_ERROR.getCode());
        }
        log.info("【策略模块】 路由策略成功 submit={}", submit);
    }
}
